<?php


namespace app\unify\controller;


use app\BaseController;
use app\unify\model\Auth as AuthModel;
use app\unify\model\Menu as MenuModel;
use app\unify\validate\Menu as MenuValidate;
use think\annotation\route\Validate;
use think\db\Query;
use think\facade\Db;
use think\Request;


class Menu extends BaseController
{
    /**
     * 菜单列表
     *
     * @return \think\Paginator
     * @throws \think\db\exception\DbException
     */
    public function index(Request $r)
    {
        $where = [];

        $keywords = $r->param('keywords');
        if ($keywords) {
            $where[] = ['title|url', 'LIKE', "%{$keywords}%"];
        }

        $pid = $r->param('pid') ?: 0;
        $where[] = ['pid', '=', $pid];


        return MenuModel::where($where)->append(['typeName', 'statusName'])->order("serial ASC, id ASC")->with(['auths'])->paginate($this->limit)->each(function ($item) {
            $item['authNames'] = implode("、", $item['auths']->map(fn($auth) => $auth['name'])->toArray());
            unset($item['auths']);
        });

    }


    /**
     * 菜单表单
     *
     * @param mixed $id
     * @param \app\unify\model\Menu $menuModel
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function form(MenuModel $menuModel, mixed $id = 0): array
    {
        $menuList = MenuModel::select()->toArray();
        $menuList = MenuModel::toTreeList($menuList, 'title');

        $authList = AuthModel::select()->toArray();

        $data = [
            'entity' => [
                'status' => MenuModel::STATUS_ENABLE,
                'type' => MenuModel::TYPE_GROUP,
                'target' => MenuModel::TARGET_SELF,
                'debug' => MenuModel::DEBUG_FALSE,
                'pid' => $this->request->param('pid') ?: 0,
                'serial' => 50
            ],
            'statusList' => MenuModel::STATUS_LIST,
            'debugList' => MenuModel::DEBUG_LIST,
            'targetList' => MenuModel::TARGET_LIST,
            'typeList' => MenuModel::TYPE_LIST,
            'menuList' => $menuList,
            'authList' => $authList
        ];

        if ($id) {
            $entity = MenuModel::find($id);
            $entity['authList'] = $entity->auths->map(fn($item) => strval($item->pivot->auth_id));
            $data['entity'] = $entity;
        }

        return $data;
    }

    /**
     * 新增菜单
     *
     * @param \think\Request $request
     * @return string
     */
    #[Validate(MenuValidate::class, scene: MenuValidate::SAVE)]
    public function save(Request $request): string
    {

        $params = $request->param();

        Db::transaction(function () use ($params) {

            $params['module'] = MenuModel::DEFAULT_MODULE;

            $menu = MenuModel::create($params);

            if (!empty($params['authList'])) {
                $menu->auths()->saveAll($params['authList']);
            }

        });

        return '操作成功';
    }

    /**
     * 菜单信息
     *
     * @param int $id
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function read($id)
    {
        $menu = MenuModel::findOrEmpty($id)->toArray();

        if (empty($menu)) {
            throw new \Exception('未找到该菜单');
        }

        $pathList = $menu['title'];
        $currPid = $menu['pid'];
        while ($currPid) {
            $currPid = 0;
            $currMenu = MenuModel::findOrEmpty($currPid)->toArray();
            if (!empty($currMenu['pid'])) {
                $currPid = $currMenu['pid'];
                array_unshift($pathList, $currMenu['title']);
            }
        }

        $menu['path'] = implode("->", $pathList);

        return $menu->toArray();
    }


    /**
     * 修改菜单
     *
     * @param \think\Request $r
     * @param int $id
     * @return string
     * @throws \Exception
     */
    #[Validate(MenuValidate::class, scene: MenuValidate::UPDATE)]
    public function update(Request $r, int $id): string
    {
        Db::transaction(function () use ($r, $id) {
            $menu = MenuModel::findOrEmpty($id);

            if (empty($menu)) {
                throw new \Exception('未找到该菜单');
            }

            $menu->save($this->request->param());
            $menu->auths()->detach();
            $menu->auths()->saveAll($r->param('authList'));
        });


        return '操作成功';
    }

    /**
     * @Notes 修改菜单字段
     * @Author EdwardCho
     * @Date 2024/1/3
     * @Time 23:48
     * @Interface updateField
     * @param \think\Request $r
     * @param array $ids
     * @param string $field
     * @param mixed $value
     * @return string
     */
    #[Validate(MenuValidate::class, scene: MenuValidate::UPDATE_FIELD)]
    public function updateField(Request $r, array $ids, string $field, mixed $value): string
    {
        MenuModel::update([
            $field => $value
        ], [
            ['id', 'in', $ids]
        ]);

        return '操作成功';
    }

    /**
     * 删除菜单
     *
     * @param int $id
     * @return string
     */
    #[Validate(MenuValidate::class, scene: MenuValidate::DELETE)]
    public function delete(array $ids): string
    {
        MenuModel::destroy(function (Query $q) use ($ids) {
            $q->where(MenuModel::getPrimaryKey(), 'in', $ids);
        });

        return '删除成功';
    }
}